package dev.werillib.widget

import android.annotation.SuppressLint
import android.content.Context
import android.content.res.TypedArray
import android.graphics.Canvas
import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import androidx.annotation.IntRange
import androidx.viewpager.widget.ViewPager
import dev.werillib.R

/**
 * create by weril 2018/11/27
 */
class SlidePointView : View {
    private var bgPointColor: Int = 0x000000
    private var fgPointColor: Int = 0xFFFFFF
    private var pointSize: Float = 10f
    private var pointNum: Int = 2
    private var pointSpacing: Float = 10f
    private lateinit var bgPointPaint: Paint
    private lateinit var fgPointPaint: Paint
    private var isFirstInit = true

    //移动进度
    private var fraction = 0f
    //当前点索引
    private var currentIndex = 0
    //当前点x坐标
    private var cX: Float = 0f
    //当前点Y坐标
    private var cY: Float = 0f

    constructor(context: Context) : super(context) {
        init(null)
    }

    constructor(context: Context, attributeSet: AttributeSet? = null) : super(context, attributeSet) {
        init(attributeSet)
    }

    private fun init(attributeSet: AttributeSet?) {
        val a: TypedArray = context.obtainStyledAttributes(attributeSet, R.styleable.SlidePointView)
        bgPointColor = a.getInt(R.styleable.SlidePointView_BgPointColor, 0x000000)
        fgPointColor = a.getInt(R.styleable.SlidePointView_FgPointColor, 0xFFFFFF)
        pointSize = a.getDimension(R.styleable.SlidePointView_PointSize, 10f)
        pointNum = a.getInt(R.styleable.SlidePointView_PointNum, 0)
        pointSpacing = a.getDimension(R.styleable.SlidePointView_PointSpacing, 10f)
        a.recycle()

        bgPointPaint = Paint()
        bgPointPaint.color = bgPointColor
        bgPointPaint.isAntiAlias = true

        fgPointPaint = Paint()
        fgPointPaint.color = fgPointColor
        fgPointPaint.isAntiAlias = true
    }

    override fun onDraw(canvas: Canvas?) {
        if (pointNum <= 1) return
        //绘制底层点
        if (isFirstInit) {
            cX = pointSize / 2
            cY = pointSize / 2
            isFirstInit = false
        }

        for (i in 1..pointNum) {
            canvas?.drawCircle(
                (pointSize / 2) * (2 * i - 1) + pointSpacing * (i - 1),
                pointSize / 2,
                pointSize / 2,
                bgPointPaint
            )
        }

        //绘制移动点
        canvas?.drawCircle(cX, cY, pointSize / 2, fgPointPaint)
    }

    fun setFraction(fraction: Float, currentIndex: Int) {
        this.fraction = fraction
        this.currentIndex = currentIndex
        cX = (pointSpacing + pointSize) * fraction +
            ((pointSize / 2) * (2 * currentIndex + 1) + pointSpacing * currentIndex)
        cY = pointSize / 2

        invalidate()
    }

    fun setViewPager(viewPager: ViewPager) {
        this.pointNum = viewPager.childCount
        viewPager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
            override fun onPageScrollStateChanged(state: Int) {

            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
                setFraction(positionOffset, position)
            }

            override fun onPageSelected(position: Int) {
            }
        })
    }

    fun setPointNum(@IntRange(from = 2) pointNum: Int) {
        this.pointNum = pointNum
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width =
            measureDimension(((pointNum * pointSize + (pointSpacing * (pointNum - 1))).toInt()), widthMeasureSpec)
        val height = measureDimension(pointSize.toInt(), heightMeasureSpec)

        setMeasuredDimension(width, height)
    }

    @SuppressLint("SwitchIntDef")
    private fun measureDimension(defaultSize: Int, spec: Int): Int {
        val specMode = MeasureSpec.getMode(spec)
        val specSize = MeasureSpec.getSize(spec)
        return when (specMode) {
            MeasureSpec.EXACTLY -> {
                defaultSize
            }
            MeasureSpec.AT_MOST -> {
                Math.min(defaultSize, specSize)
            }
            else -> {
                defaultSize
            }
        }
    }
}